package com.rabbiter.hospital.controller;

import com.rabbiter.hospital.mapper.OrderMapper;
import com.rabbiter.hospital.pojo.Orders;
import com.rabbiter.hospital.pojo.Patient;
import com.rabbiter.hospital.service.DoctorService;
import com.rabbiter.hospital.service.OrderService;
import com.rabbiter.hospital.service.PatientService;
import com.rabbiter.hospital.utils.JwtUtil;
import com.rabbiter.hospital.utils.PdfUtil;
import com.rabbiter.hospital.utils.ResponseData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("patient")
public class PatientController {

    @Autowired
    private DoctorService doctorService;
    @Autowired
    private PatientService patientService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private JedisPool jedisPool;
    @Resource
    private OrderMapper orderMapper;

    /**
     * 登录数据验证
     * 该方法通过接收患者ID和密码，验证患者信息并生成认证令牌
     * 如果登录成功，返回包含患者基本信息和认证令牌的数据
     * 如果登录失败，返回错误信息
     * @param pId       患者ID
     * @param pPassword 患者密码
     * @return 包含状态和消息的响应数据对象
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ResponseBody
    public ResponseData login(@RequestParam(value = "pId") int pId, @RequestParam(value = "pPassword") String pPassword) {
        // 调用服务层的登录方法，进行患者身份验证
        Patient patient = this.patientService.login(pId, pPassword);
        // 如果找到匹配的患者信息，表示登录成功
        if (patient != null) {
            // 创建一个Map来存储将要放入JWT令牌的信息
            Map<String, String> map = new HashMap<>();
            // 将患者姓名、ID和医疗卡信息放入Map中
            map.put("pName", patient.getPName());
            map.put("pId", String.valueOf(patient.getPId()));
            map.put("pCard", patient.getPCard());
            // 使用JwtUtil工具类生成认证令牌
            String token = JwtUtil.getToken(map);
            // 将生成的令牌放入Map中
            map.put("token", token);
            // 另一种方式设置响应头中的令牌
            //response.setHeader("token", token);
            // 返回登录成功的响应数据，包含患者信息和令牌
            return ResponseData.success("登录成功", map);
        } else {
            // 登录失败，返回错误信息
            return ResponseData.fail("登录失败，密码或账号错误");
        }
    }

    /**
     * 根据科室查询所有医生信息
     * 该方法通过科室名称筛选并返回所有属于该科室的医生信息
     * 使用了Spring MVC的@RequestMapping注解，映射到特定的URL上，处理HTTP GET请求
     * @param dSection 科室名称，用于筛选医生
     * @return ResponseData 包含查询结果的响应对象，成功时包含所有医生信息
     */
    @RequestMapping("findDoctorBySection")
    public ResponseData findDoctorBySection(@RequestParam(value = "dSection") String dSection) {
        // 调用医生服务的查询方法，根据科室名称获取所有医生信息，并返回成功响应
        return ResponseData.success("根据科室查询所有医生信息成功", this.doctorService.findDoctorBySection(dSection));
    }

    /**
     * 增加挂号信息
     * 通过此方法，将用户提交的挂号信息添加到系统中，并根据操作结果返回相应的响应数据
     * @param order 挂号信息对象，包含挂号的所有详细信息
     * @param arId  授权相关的ID，用于处理与授权相关的逻辑（例如医生或诊所的ID）
     * @return 返回一个ResponseData对象，其中包含操作结果的状态和消息
     * 注解说明：
     * - @RequestMapping("addOrder")：指定处理"/addOrder"请求的URL
     * - @ResponseBody：表示该方法的返回值将直接写入HTTP响应体中，而不是渲染为视图页面
     */
    @RequestMapping("addOrder")
    @ResponseBody
    public ResponseData addOrder(Orders order, String arId) {
        // 打印接收到的授权ID，用于调试目的
        System.out.println(arId);
        // 调用服务层方法添加挂号信息，根据返回结果判断操作是否成功
        if (this.orderService.addOrder(order, arId)) return ResponseData.success("插入挂号信息成功");
        return ResponseData.fail("插入挂号信息失败");
    }

    /**
     * 根据患者ID查询挂号信息
     * @param pId 患者ID，用于查询对应的挂号信息
     * @return ResponseData 包含挂号信息的响应数据对象
     */
    @RequestMapping("findOrderByPid")
    public ResponseData findOrderByPid(@RequestParam(value = "pId") int pId) {
        // 返回通过患者ID查询到的挂号信息
        return ResponseData.success("返回挂号信息成功", this.orderService.findOrderByPid(pId));
    }


    /**
     * 增加患者信息
     * 该方法用于注册新患者，通过接收Patient对象作为参数，
     * 调用患者服务（patientService）的addPatient方法尝试添加患者信息，
     * 并根据操作结果返回相应的响应数据。
     * @param patient 患者对象，包含患者的所有个人信息
     * @return 返回ResponseData对象，包含操作结果和消息
     * 如果患者信息添加成功，则返回成功消息
     * 否则，返回失败消息，提示账号或邮箱已被占用
     */
    @RequestMapping("addPatient")
    @ResponseBody
    public ResponseData addPatient(Patient patient) {
        Boolean bo = this.patientService.addPatient(patient);
        if (bo) {
            return ResponseData.success("注册成功");
        }
        return ResponseData.fail("注册失败！账号或邮箱已被占用");
    }

    /**
     * 控制器方法，用于下载订单的PDF文件
     * @param request  HTTP请求对象，用于获取请求信息
     * @param response HTTP响应对象，用于设置响应头和返回响应数据
     * @param oId      订单ID，用于标识要下载的订单
     * @throws Exception 如果在处理请求时发生错误，则抛出异常
     */
    @GetMapping("/pdf")
    public void downloadPDF(HttpServletRequest request, HttpServletResponse response, int oId) throws Exception {
        // 通过订单ID查询订单信息
        Orders order = this.orderMapper.findOrderByOid(oId);
        // 将订单信息导出为PDF
        PdfUtil.ExportPdf(request, response, order);
    }

    /**
     * 统计患者男女人数
     * 通过patientService调用patientAge方法获取患者男女人数统计结果
     * 使用ResponseData的success方法包装返回结果，确保前端可以接收到成功响应
     */
    @RequestMapping("patientAge")
    public ResponseData patientAge() {
        // 统计患者男女人数的具体实现，调用patientService中的patientAge方法获取数据
        // 返回封装好的响应数据，包括成功信息和统计数据
        return ResponseData.success("统计患者男女人数成功", this.patientService.patientAge());
    }


}
